7.3 defer
有这样一种场景,就是我们需要在函数执行结束之后进行一些操作。
比如我们通过代码打开了文件,那么我们需要保证在读取完文件以后,将文件进行关闭,这时候我们就会使用到defer
。
那么可能我们会有疑问,直接在读取完成以后直接关闭就可以了,为什么还要使用defer
呢?
我们思考一种情况:当读取函数执行到一半的时候,发生panic
导致了程序崩溃,这时候函数最后的关闭代码就肯定不会被执行了。
这种情况下,就可能会出现一些未知的问题。所以出现了defer
,使用defer
就可以保证文件关闭代码一定被执行,哪怕发生了panic
,关闭代码同样会被执行。
本节代码存放目录为 lesson21
使用defer
上面我们了解到了defer
的基本概念,接下来我们就尝试去使用看一下他的执行流程。代码如下所示:
func main() {
deferPrint()
}
func deferPrint() {
fmt.Printf("函数进入...\n")
defer fmt.Println("函数结束,defer逻辑调用...")
fmt.Printf("函数执行...\n")
fmt.Printf("函数return...\n")
return
}
执行上面的代码,结果输出如下:
函数进入...
函数执行...
函数return...
函数结束,defer逻辑调用...
从上面的代码中,我们可以看到defer
是在最后调用的,这也就反映出了defer
的特点。
下面我们演示panic
时defer
的执行情况。代码如下所示:
func deferPanic() {
fmt.Printf("函数进入...\n")
defer fmt.Println("函数结束,defer逻辑调用...")
fmt.Printf("函数执行...\n")
panic(errors.New("执行出错"))
fmt.Printf("函数return...\n")
return
}
指向上面的代码,结果输出如下所示:
函数进入...
函数执行...
函数结束,defer逻辑调用...
panic: 执行出错
goroutine 1 [running]:
main.deferPanic()
/Users/xc/xcWork/YouCanGo/Code/YouCanGoCode/lesson21/lesson21.go:33 +0x151
main.main()
/Users/xc/xcWork/YouCanGo/Code/YouCanGoCode/lesson21/lesson21.go:11 +0x2a
exit status 2
从上面的输出我们可以看出,函数执行以后发生了panic
,这时候defer
的代码仍然被调用了。
也就是说,当发生panic
的时候,defer
的逻辑同样是可以执行的,这有点类似于Java
的finally
小结
本节我们介绍了defer
,并且对defer
进行了实际的测试。
关于本节总结如下:
defer
在函数结束后调用发生
panic
时defer
的逻辑仍然会执行defer
常用于在函数中关闭一些打开的资源,比如文件关闭